package net.vinote.smart.platform.base;

import java.io.InputStream;
import java.sql.SQLException;
import java.util.Hashtable;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.logging.Level;

import net.vinote.smart.platform.comm.PlatformConst;
import net.vinote.smart.platform.module.database.DBFactory;
import net.vinote.smart.platform.module.i18n.Message;
import net.vinote.smart.platform.module.log.RunLogger;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

/**
 * 存储了系统运行所依赖的参数对象
 * 
 * @author 郑俊伟
 * @version 1.0
 * @since JDK1.6
 */
public class Platform {
	private static final RunLogger logger = RunLogger.getLogger();
	protected static Platform platform;

	/** 是否已初始化 */
	private boolean inited = false;

	/** 重写put() putAll()的实现,时存入的键为小写 */
	private Hashtable<String, Object> configs = new Hashtable<String, Object>() {
		private static final long serialVersionUID = 8157872564126595724L;

		@Override
		public synchronized Object put(String key, Object value) {
			return super.put(key.toLowerCase(), value);
		}

		@Override
		public synchronized void putAll(
				Map<? extends String, ? extends Object> t) {
			for (Map.Entry<? extends String, ? extends Object> e : t.entrySet())
				put(e.getKey().toLowerCase(), e.getValue());
		}

	};

	public static Platform getInstance() {
		if (platform == null) {
			synchronized ("") {
				if (platform == null) {
					platform = new Platform();
				}
			}
		}
		return platform;
	}

	protected Platform() {
	}

	public final boolean loadCfg(InputStream in) {
		configs.clear();
		try {
			SAXReader read = new SAXReader();
			Document doc = read.read(in);
			Element rootElement = doc.getRootElement();
			if (!"ServerRuntimeEvn".equals(rootElement.getName())) {
				throw new RuntimeException("不存在根目录ServejrRuntimeEvn");
			}
			configs.put("appName", rootElement.element("appName")
					.getStringValue());
			configs.put("locale", rootElement.element("locale")
					.getStringValue());
			List<Element> subRoot = rootElement.elements("server");
			String serverName;
			List<Element> paramElement;
			for (Element e : subRoot) {
				serverName = e.attributeValue("name");
				paramElement = e.elements("param");
				for (Element pE : paramElement) {
					configs.put(serverName + "." + pE.attributeValue("name"),
							pE.getStringValue());
				}
			}
		} catch (DocumentException e1) {
			logger.log(Level.WARNING, e1.getMessage(), e1);
		}
		return true;
	}

	/**
	 * 加载缓存数据
	 * 
	 * @throws SQLException
	 */
	public boolean initializ() throws SQLException {
		// 加载资源文件
		Message msg = new Message();
		msg.addI18N("Application", Message.class.getClassLoader());
		String local[] = getLocale().split("_");
		msg.setLocal(new Locale(local[0], local[1]));
		configs.put(PlatformConst.PLATFORM_PREFIX_MODULE + "I18N", msg);
		return true;
	}

	/**
	 * 获取SRE中存储的属性值
	 * 
	 * @param key
	 *            用于查找的键值
	 * @return value
	 */
	public final static String getAttribute(String key) {
		return getAttribute(key, String.class);
	}

	/**
	 * 获取期望类型的属性值
	 * 
	 * @param <T>
	 *            返回值的类型
	 * @param key
	 *            用于查找的键值
	 * @param clazz
	 *            查找的值所对应的类型
	 * @return T
	 */
	@SuppressWarnings("unchecked")
	public static <T> T getAttribute(String key, Class<T> clazz) {
		Object obj = getInstance().configs.get(key.toLowerCase());
		/*
		 * if (obj == null) { throw new NullPointerException("SRE中不存在指定属性:" +
		 * key); }
		 */
		if (clazz.isInstance(obj)) {
			return (T) obj;
		}
		return null;
	}

	/**
	 * 获取期望类型的属性值,若找不到对应的数据,则返回nulls
	 * 
	 * @param <T>
	 *            返回值的类型
	 * @param key
	 *            用于查找的键值
	 * @param clazz
	 *            查找的值所对应的类型
	 * @return T
	 */
	public final static <T> T getAttributeMaybeNull(String key, Class<T> clazz) {
		Object obj = getInstance().configs.get(key.toLowerCase());
		if (obj != null) {
			if (clazz.isInstance(obj)) {
				return (T) obj;
			}
		}
		return null;
	}

	public final static void addAttribute(PlatformModify<?> modify) {
		if (modify instanceof SysPlatformModify) {
			logger.log(Level.FINE, "Load System Level SRE Property");
			for (String key : modify.getAttributes().keySet()) {
				getInstance().configs.put(key, modify.getAttribute(key));
				logger.log(Level.FINE,
						"load property" + key + "=" + modify.getAttribute(key));
			}
			logger.log(Level.FINE, "load system level SRE property success!");
		} else {
			logger.log(Level.FINE, "load business level SRE property success");
			for (String key : modify.getAttributes().keySet()) {
				getInstance().configs.put(modify.getClass().getName() + "."
						+ key, modify.getAttribute(key));
				logger.log(Level.FINE, "load property"
						+ modify.getClass().getName() + "." + key + "="
						+ modify.getAttribute(key));
			}
		}
	}

	public String getLocale() {
		return (String) configs.get("locale");
	}

	public static Message getI18nMessage() {
		return getAttribute(PlatformConst.PLATFORM_PREFIX_MODULE + "I18N",
				Message.class);
	}

	/**
	 * 释放资源
	 */
	public void release() {
		logger.log(
				Level.FINE,
				Platform.getI18nMessage().getMessage(
						"com.zjw.platform.base.release"));
		DBFactory.getFactory().destroy();

		// 保留资源信息
		Message msg = getI18nMessage();
		configs.clear();
		configs.put(PlatformConst.PLATFORM_PREFIX_MODULE + "I18N", msg);
	}

	public void hasInitialized() {
		inited = true;
	}

	public boolean isInitialized() {
		return inited;
	}
}
